#ifndef __BITFIELD_H__
#define __BITFIELD_H__

namespace inf {

    template< int MAX_BITS >
    class BitField
    {
    private:
        static const int	INTBITS		= sizeof( int ) * 8;
        static const int	INTBITS_X	= INTBITS - 1;
        static const int	SIZE		= ( MAX_BITS / INTBITS ) + 1;

    public:
                            BitField( void ) { clear(); }

        int					total_size( void ) const { return SIZE; }

        void				operator= ( const BitField& other ) { memory_copy( bits, other.bits, sizeof( bits ) ); }
        int					operator[] ( int bit ) const { return get( bit ); }
        bool				operator!= ( const BitField& other ) const { return memcmp( bits, other.bits, sizeof( bits ) ) != 0; }
        bool				operator== ( const BitField& other ) const { return !(operator!=(other)); }	
        int					get( int bit ) const { return ( ( bits[ bit / INTBITS ] >> ( bit & INTBITS_X ) ) & 1 ); }
        void				set( int bit ) { bits[ bit / INTBITS ] |= 1 << ( bit & INTBITS_X ); }
        void				clear( int bit ) { bits[ bit / INTBITS ] &= ~( 1 << ( bit & INTBITS_X ) ); }

        void				clear( void ) { memory_set( bits, 0, sizeof( bits ) ); }
        void				set_all( void ) { memory_set( bits, 1, sizeof( bits ) ); }

        int*				get_direct( void ) { return bits; }
        const int*	        get_direct( void ) const { return bits; }
    private:
        int					bits[ SIZE ];
    };

    class BitField_Dynamic
    {
    private:
        static const int	INTBITS		= sizeof( int ) * 8;
        static const int	INTBITS_X	= INTBITS - 1;

        static int			sizeForBits( int bits ) { return ( bits / INTBITS ) + 1; }
    public:
                            BitField_Dynamic( void ) { bits = NULL; size = 0; }
                            ~BitField_Dynamic( void ) { shutdown(); }

        void				init( int MAX_BITS ) { reset_size( sizeForBits( MAX_BITS ) ); }
        void				shutdown( void ) { delete[] bits; bits = NULL; size = 0; }

        int					total_size( void ) const { return size; }
        void				reset_size( int size ) { if ( this->size == size ) { return; } shutdown(); this->size = size; if ( size > 0 ) { bits = new int[ size ]; } }

        int					operator[] ( int bit ) const { return get( bit ); }
        int					get( int bit ) const { return ( ( bits[ bit / INTBITS ] >> ( bit & INTBITS_X ) ) & 1 ); }
        void				set( int bit ) { bits[ bit / INTBITS ] |= 1 << ( bit & INTBITS_X ); }
        void				clear( int bit ) { bits[ bit / INTBITS ] &= ~( 1 << ( bit & INTBITS_X ) ); }

        void				clear( void ) { if( bits ) { memory_set( bits, 0, size * sizeof( int ) ); } }
        void				set_all( void ) { memory_set( bits, 1, size * sizeof( int ) ); }

        int&				get_direct( int index ) { return bits[ index ]; }
        const int&	        get_direct( int index ) const { return bits[ index ]; }
    private:
        int*				bits;
        int					size;
    };

}   // ::inf

#endif /* !__BITFIELD_H__ */
